<?php
/**
 *	[TWCMS] (C)2012 TongWang Inc.
 *	$Id: global.func.php 2 2013-04-27 07:14:17Z nanown@qq.com $
 */
defined('IN_TWCMS') || exit('Access Denied');

#生成静态
function get_front() {
	ob_start();
	require TWCMS_FRONT.'index.php';
	$str = ob_get_contents();
	ob_end_clean();
	return $str;
}

#安全过滤
function S($str, $quot="'") {
	return is_numeric($str) ? $str : $quot.addslashes($str).$quot;
}

#检查是否符合路径字符串
function checkLaw($str, $isLine=true) {
	if(empty($str) || strstr($str, '..')!==false) {
		return false;
	}
	if($isLine && (strstr($str, '\\')!==false || strstr($str, '/')!==false)) {
		return false;
	}
	return true;
}

#返回安全int
function intC(&$C, $K, $V=0) {
	return isset($C[$K]) ? intval($C[$K]) : $V;
}

#返回安全numeric
function _intC(&$C, $K, $V=0) {
	if(empty($C[$K])) return $V;
	if(is_numeric($C[$K])) return $C[$K];
	$ret = '';
	foreach(explode(',', $C[$K]) as $val) {
		if(is_numeric($val) || $val=intval($val)) {
			$ret .= $val.',';
		}
	}
	$ret = trim($ret, ',');
	return $ret ? $ret : $V;
}

#过滤字符串两端空格
function strC(&$C, $K, $V='') {
	return isset($C[$K]) ? trim($C[$K]) : $V;
}

#过滤GET数值
function intget($key, $val=0) {
	return isset($_GET[$key]) ? intval($_GET[$key]) : $val;
}

#正则清理非数字字符串
function int_preg($str) {
	return preg_replace('/\D/','',$str);
}

#正则清理非字母,数字,_的字符串
function str_preg($str) {
	return preg_replace('/\W/','',$str);
}

#递归加反斜线
function _addslashes($val) {
	if(!is_array($val)) return addslashes($val);
	foreach($val as $k => $v) $val[$k] = _addslashes($v);
	return $val;
}

#递归清理反斜线
function _stripslashes($val) {
	if(!is_array($val)) return stripslashes($val);
	foreach($val as $k => $v) $val[$k] = _stripslashes($v);
	return $val;
}

#递归转换为HTML实体代码
function _htmls($val) {
	if(!is_array($val)) return htmlspecialchars($val);
	foreach($val as $k => $v) $val[$k] = _htmls($v);
	return $val;
}

#递归清理两端空白字符
function _trim($val) {
	if(!is_array($val)) return trim($val);
	foreach($val as $k => $v) $val[$k] = _trim($v);
	return $val;
}

#递归创建目录
function _mkdir($dir, $isindex = true, $mode = 0777){
	if(is_dir($dir)) return true;
	if(_mkdir(dirname($dir), $mode)) {
		if(mkdir($dir, $mode)) {
			if($isindex) {
				touch($dir.'/index.htm');
				chmod($dir.'/index.htm', 0777);
			}
			return true;
		}
	}
	return false;
}

#递归删除文件夹（有返回信息）
function del_dir($path) {
	if($dh = opendir($path)) {
		$fileerr = $direrr = $filenum = $dirnum = $size = 0;
		while (($file = readdir($dh)) !== false) {
			if($file!='.' && $file!='..') {
				$files = $path.D.$file;
				if(is_dir($files)) {
					if($ret = del_dir($files)) {
						$fileerr += $ret['fileerr']; $direrr += $ret['direrr'];
						$filenum += $ret['filenum']; $dirnum += $ret['dirnum']; $size += $ret['size'];
					}
				}else{
					$byte = filesize($files);
					if(unlink($files)) { $filenum++; $size+=$byte; } else $fileerr++;
				}
			}
		}
		closedir($dh);
		if(rmdir($path)) $dirnum++; else $direrr++;
		return array('fileerr'=>$fileerr, 'direrr'=>$direrr, 'filenum'=>$filenum, 'dirnum'=>$dirnum, 'size'=>$size);
	}
}

#递归删除文件夹
function delDir($dir) {
	$dh = opendir($dir);
	while(($file=readdir($dh)) !== false) {
		if($file != '.' && $file != '..') {
			$fullpath = $dir.D.$file;
			if(!is_dir($fullpath)) {
				unlink($fullpath);
			}else{
				delDir($fullpath);
			}
		}
	}
	closedir($dh);
	return rmdir($dir);
}

#检测目录是否可写
function is_dir_write($dir) {
	$ret = false;
	if(!is_dir($dir)) {
		@mkdir($dir, 0777);
	}
	if(is_dir($dir)) {
		if($fp = @fopen($dir.D.'test.txt', 'w')) {
			@fclose($fp);
			@unlink($dir.D.'test.txt') && $ret = true;
		}
	}
	return $ret;
}

#递归检测目录/文件是否写
function _dir_write($dir) {
	if(!is_dir($dir)) return false;
	$ret = true;
	if(!is_dir_write($dir)) {
		$GLOBALS['err_file'][] = $dir; $ret = false;
	}

	if($dh = opendir($dir)) {
		while (($file = readdir($dh)) !== false) {
			if($file!='.' && $file!='..') {
				$fileson = $dir.D.$file;
				if(is_dir($fileson)) {
					if(!_dir_write($fileson)) {
						$GLOBALS['err_file'][] = $fileson; $ret = false;
					}
				}else{
					if(!is_writable($fileson)) {
						$GLOBALS['err_file'][] = $fileson; $ret = false;
					}
				}
			}
		}
		closedir($dh);
	}
	return $ret;
}

#清空缓存文件
function un_cache($dir) {
	_mkdir($dir);
	$ret = true;
	if($directory = @dir($dir)) {
		while($entry = $directory->read()) {
			$filename = $dir.D.$entry;
			if(is_file($filename)) {
				@unlink($filename) || $ret = false;
			}
		}
		$directory->close();
		@touch($dir.D.'index.htm');
	}
	return $ret;
}

#加载后台模板
function load_tpl($tplname) {
	return TWCMS_ADMCORE.'tpl'.D.$tplname.'.tpl.php';
}

#加载错误提示
function loadErr($cont) {
	$file = base::load_sys_file('twcms_err', 'twcms');
	if(file_exists($file)) {
		include $file;exit();
	}else{
		exit($cont);
	}
}

#获取IP地址
function ip() {
	if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
		$ip = getenv('HTTP_CLIENT_IP');
	} elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
		$ip = getenv('HTTP_X_FORWARDED_FOR');
	} elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
		$ip = getenv('REMOTE_ADDR');
	} elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
		$ip = $_SERVER['REMOTE_ADDR'];
	}
	return preg_match('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#', $ip, $matches) ? $matches[0] : '';
}

#简单的数组转JSON
function tojson($arr) {
	if(!is_array($arr)) return false; 
	$str = '{';
	foreach($arr as $k=>$v) {
		$str .= '"'.$k.'":"'.strtr($v, array('\\'=>'\\\\', '"'=>'\"')).'",';
	}
	return rtrim($str, ',').'}';
}

#获取系统编辑器配置信息
function getTwEditor(&$G) {
	$str = '<script type="text/javascript">window.TW_EDITOR={';
	$str .= 'editorUrl:"'.TWCMS_EDITOR.'",';
	$str .= 'jsonUrl:"'.ADMNAME.'?mod=json&do=",';
	$str .= 'postParams:{"'.TW_UPID.'":"'.$_COOKIE[TW_COOKIEPRE.'admauth'].'"},';
	$str .= 'imageExtension:"'.toExt($G['up_img_ext']).'",';
	$str .= 'fileSizeLimit:"'.get_byte($G['up_file_max_size']*1024).'",';
	$str .= 'fileTypes:"'.toExt($G['up_file_ext']).'"';
	return $str .= '}</script>';
}

#分割SQL语句
function splitsql($sql) {
	$sql = str_replace("\r", "\n", $sql);
	$ret = array();
	$num = 0;
	$queriesarray = explode(";\n", trim($sql));
	unset($sql);
	foreach($queriesarray as $query) {
		$ret[$num] = isset($ret[$num]) ? $ret[$num] : '';
		$queries = explode("\n", trim($query));
		foreach($queries as $query) {
			$ret[$num] .= isset($query[0]) && $query[0] == "#" ? NULL : $query;
		}
		$num++;
	}
	return $ret;
}

/**
 * 输出Json字符串
 * @param string $err 状态
 * @param string $msg 消息
 */
function ret_json($err, $msg) {
	exit('{"err" : '.($err ? 0 : 1).', "msg" : "'.$msg.'"}');
}

/**
 * 输出表格TR
 * @param string $th 表单名
 * @param string $val 值
 * @param string $type 类型
 * @param string $name 表单名
 * @param string $desc 描述
 * @param string $class 自定义CSS类
 */
function load_tr($th, $val, $type='', $name='', $desc='', $class=""){
	echo '<tr><th>'.$th.'</th><td>';

	switch ($type) {
		case 'text':
			echo '<input name="'.$name.'" type="text" value="'.htmlspecialchars($val).'" class="inp '.(empty($class) ? 'w1' : $class).'" />';
			break;
		case 'password':
			echo '<input name="'.$name.'" type="password" value="'.$val.'" class="inp '.(empty($class) ? 'w2' : $class).'" />';
			break;
		case 'textarea':
			echo '<textarea name="'.$name.'" class="inp '.(empty($class) ? 'w3' : $class).'">'.htmlspecialchars($val).'</textarea>';
			break;
		case 'number':
			echo '<input name="'.$name.'" type="number" step="1" min="0" value="'.$val.'" class="inp wnum">';
			break;
		case 'yesno':
			echo '<label><input class="mr3" name="'.$name.'" type="radio" value="1"'.($val==1 ? ' checked="checked"' : '').'>&#26159;</label>';
			echo '<label><input class="mr3" name="'.$name.'" type="radio" value="0"'.($val==0 ? ' checked="checked"' : '').'>&#21542;</label>';
			break;
		default:
			echo $val;
	}
	if(!empty($desc)) echo '<p class="desc">'.$desc.'</p>';

	echo '</td></tr>';
}

/**
 * 输出表格TR
 * @param string $type 类型
 * @param string $name 表单名
 * @param string $arr 分类数组
 * @param string $on 默认选中值
 * @param string $br 是否换行
 */
function for_val($type, $name, $arr, $on, $br=true){
	$str = '';
	switch ($type) {
		case 'radio':
			foreach ($arr as $a1){
				$str.='<label><input class="mr3" name="'.$name.'" type="radio" value="'.$a1[0].'"'.($a1[0]==$on ? ' checked="checked"' : '').'>'.$a1[1].'</label>';
				if($br) $str.='<br>';
			}
			break;
		case 'checkbox':
			foreach ($arr as $a1){
				$str.='<label><input class="mr3" name="'.$name.'[]" type="checkbox" value="'.$a1[0].'"'.(in_array($a1[0],explode(',', $on)) ? ' checked="checked"' : '').'>'.$a1[1].'</label>';
				if($br) $str.='<br>';
			}
			break;
		case 'select':
			$str.='<select name="'.$name.'" class="se1">';
			foreach ($arr as $a1){
				$str.='<option value="'.$a1[0].'"'.($a1[0]==$on ? ' selected="selected"' : '').'>'.$a1[1].'</option>';
			}
			$str.='</select>';
			break;
		case 'multiple':
			$str.='<select name="'.$name.'[]" multiple="multiple" class="se2">';
			foreach ($arr as $a1){
				$str.='<option value="'.$a1[0].'"'.(in_array($a1[0],explode(',', $on)) ? ' selected="selected"' : '').'>'.$a1[1].'</option>';
			}
			$str.='</select>';
			break;
	}
	return $str;
}

/**
 * 分页函数
 * @param string $total 总数
 * @param string $page 当前页
 * @param string $pagenum 每页多少条
 * @param string $purl URL
 * @param string $offset 偏移数
 */
function page($total, $page, $pagenum, $purl, $offset=5) {
	$maxpage=ceil($total/$pagenum);
	$GLOBALS['html_maxpage']=&$maxpage; 
	if($maxpage<2) return '';
	$page=$page>$maxpage ? $maxpage : $page;

	$str='<b>共: <font color="red">'.$total.'</font></b>';
	if($page>1){
		$str.='<a href="'.sprintf($purl,1).'">首页</a>';
		$str.='<a href="'.sprintf($purl,($page-1)).'">上一页</a>';
	}

	$i= $page>$offset ? $page-$offset+1 : 1 ;
	$i_end= ($page+$offset*2)>$maxpage ? $maxpage  : ($page+$offset<$offset*2 ? $offset*2 : $page+$offset);

	for($i;$i<=$i_end;$i++){
		if($page==$i) $str.='<b>'.$i.'</b>';
		else $str.='<a href="'.sprintf($purl,$i).'">'.$i.'</a>';
	}

	if($page<$maxpage){
		$str.='<a href="'.sprintf($purl,($page+1)).'">下一页</a>';
		$str.='<a href="'.sprintf($purl,$maxpage).'">尾页</a>';
	}
	return $str;
}

/**
 * 字符串转Unicode编码
 * @param string $str 原始中文字符串
 * @param string $encoding 原始字符串的编码
 * @param string $prefix 编码后的前缀
 * @param string $postfix 编码后的后缀
 */
function unicode_encode($str, $encoding = 'UTF-8', $prefix = '&#', $postfix = ';') {
	$str = iconv($encoding, 'UCS-2', $str);
	$arrstr = str_split($str, 2);
	$unistr = '';
	for($i = 0, $len = count($arrstr); $i < $len; $i++) {
		$dec = hexdec(bin2hex($arrstr[$i]));
		$unistr .= $prefix . $dec . $postfix;
	} 
	return $unistr;
}

/**
 * Unicode编码转字符串
 * @param string $str Unicode编码后的字符串
 * @param string $encoding 原始字符串的编码
 * @param string $prefix 编码字符串的前缀
 * @param string $postfix 编码字符串的后缀
 */
function unicode_decode($unistr, $encoding = 'UTF-8', $prefix = '&#', $postfix = ';') {
	$arruni = explode($prefix, $unistr);
	$unistr = '';
	for($i = 1, $len = count($arruni); $i < $len; $i++) {
		if (strlen($postfix) > 0) {
			$arruni[$i] = substr($arruni[$i], 0, strlen($arruni[$i]) - strlen($postfix));
		} 
		$temp = intval($arruni[$i]);
		$unistr .= ($temp < 256) ? chr(0) . chr($temp) : chr($temp / 256) . chr($temp % 256);
	} 
	return iconv('UCS-2', $encoding, $unistr);
}

/**
 * 提示框（默认没有数据时提示）
 * @param string $str 提示文字
 * @param string $css CSS样式类名
 */
function skyTips($str, $css='sky warning bnote') {
	echo '<div class="'.$css.'"><i></i><b>'.$str.'</b></div>';
}

/**
 * 获取数据大小单位
 * @param int $byte 字节
 */
function get_byte($byte) {
	if($byte < 1024) {
		return $byte.' Byte';
	}elseif($byte < 1048576) {
		return round($byte/1024,2).' KB';
	}elseif($byte < 1073741824) {
		return round($byte/1048576,2).' MB';
	}elseif($byte < 1099511627776) {
		return round($byte/1073741824,2).' GB';
	}else{
		return round($byte/1099511627776,2).' TB';
	}
}

/**
 * 转换文件扩展名
 * @param string $ext “,”分割的扩展名
 */
function toExt($ext) {
	$Arr = explode(',', $ext);
	$ret = array();
	foreach($Arr as $val) {
		$val = trim($val);
		if($val) $ret[] = $val;
	}
	return '*.'.implode(';*.', $ret);
}

/**
 * 读取文件
 * @param string $file 文件路径
 */
function f_read($file) {
	if(function_exists('file_get_contents')) return file_get_contents($file);

	$ft=fopen($file,"rb");
	$str='';
	while (!feof($ft)) {
		$str.=fread($ft,4096);
	}
	fclose($ft);
	return $str;
}

/**
 * 写入文件
 * @param string $file 文件路径
 * @param string $str 写入字符串
 */
function f_write($file, $str) {
	if(function_exists('file_put_contents')) return file_put_contents($file,$str,LOCK_EX);

	$ft=fopen($file,'wb');
	flock($ft,LOCK_UN);
	flock($ft,LOCK_EX|LOCK_NB);
	$rn=fwrite($ft,$str);
	flock($ft,LOCK_UN);
	fclose($ft);
	return $rn;
}

/**
* 字符串加密、解密函数
* @param	string	$txt		字符串
* @param	string	$operation	ENCODE为加密，DECODE为解密，可选参数，默认为ENCODE，
* @param	string	$key		密钥：数字、字母、下划线
* @param	string	$expiry		过期时间
*/
function sys_auth($string, $operation = 'ENCODE', $key = '', $expiry = 0) {
	$key_length = 4;
	$key = md5($key != '' ? $key : TW_KEY);
	$fixedkey = md5($key);
	$egiskeys = md5(substr($fixedkey, 16, 16));
	$runtokey = $key_length ? ($operation == 'ENCODE' ? substr(md5(microtime(true)), -$key_length) : substr($string, 0, $key_length)) : '';
	$keys = md5(substr($runtokey, 0, 16) . substr($fixedkey, 0, 16) . substr($runtokey, 16) . substr($fixedkey, 16));
	$string = $operation == 'ENCODE' ? sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$egiskeys), 0, 16) . $string : base64_decode(substr($string, $key_length));

	$i = 0; $result = '';
	$string_length = strlen($string);
	for ($i = 0; $i < $string_length; $i++){
		$result .= chr(ord($string{$i}) ^ ord($keys{$i % 32}));
	}
	if($operation == 'ENCODE') {
		return $runtokey . str_replace('=', '', base64_encode($result));
	} else {
		if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$egiskeys), 0, 16)) {
			return substr($result, 26);
		} else {
			return '';
		}
	}
}

/**
 * 字符截取 支持UTF8/GBK
 * @param $string
 * @param $length
 * @param $dot
 */
function dstr($string, $length, $dot='...', $start=0, $charset='utf-8') {
	$string=str_replace(array('&amp;','&quot;','&lt;','&gt;','&nbsp;','&#160;'),array('&','"','<','>',' ',' '),$string);
	if (strlen($string)<=$length) return $string;
	$strcut='';
	if (strtolower($charset)=='utf-8') {
		$n=$tn=$noc=0;
		while ($n<strlen($string)) {
			$t=ord($string[$n]);
			if ($t==9 || $t==10 || (32<=$t && $t<=126)) {
				$tn=1;
				$n++;
				$noc++;
			}elseif (194<=$t && $t<=223) {
				$tn=2;
				$n+=2;
				$noc+=2;
			}elseif (224<=$t && $t<239) {
				$tn=3;
				$n+=3;
				$noc+=2;
			}elseif (240<=$t && $t<=247) {
				$tn=4;
				$n+=4;
				$noc+=2;
			}elseif (248<=$t && $t<=251) {
				$tn=5;
				$n+=5;
				$noc+=2;
			}elseif ($t==252 || $t==253) {
				$tn=6;
				$n+=6;
				$noc+=2;
			}else{
				$n++;
			}
			if ($noc>=$length) break;
		}
		if ($noc>$length) $n-=$tn;
		$strcut=substr($string,$start,$n);
	}else{
		for ($i=$start;$i<$start+$length-strlen($dot)-1;$i++) {
			$strcut.=ord($string[$i])>127 ? $string[$i].$string[++$i] : $string[$i];
		}
	}
	return $strcut.$dot;
}

/**
 * 输出JS跳转代码
 * @param string $url 跳转地址
 * @param string $str 弹出提示内容
 */
function jsjump($url, $str=''){
	$cont = $str ? 'alert("'.$str.'");' : '';
	$cont .= $url ? 'location.href="'.$url.'";' : 'window.history.back();';
	exit('<script type="text/javascript">'.$cont.'</script>');
}

/**
* 产生随机字符串
* @param int	$length	输出长度
* @param int	$type	输出类型 1为数字 2为Aa1 3为a1
* @param string	$chars	随机字符 可自定义
*/
function random($length, $type = 1, $chars = '0123456789abcdefghijklmnopqrstuvwxyz') {
	PHP_VERSION < '4.2.0' && mt_srand((double)microtime() * 1000000);
	if($type == 1) {
		$hash = sprintf('%0'.$length.'d', mt_rand(0, pow(10, $length) - 1));
	} else {
		$hash = '';
		if($type == 2) $chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
		$max = strlen($chars) - 1;
		for($i = 0; $i < $length; $i++) $hash .= $chars[mt_rand(0, $max)];
	}
	return $hash;
}